BERT: Bidirectional Encoder Representations from Transformers
You are what you eat.
And I'm cooking what I eat! :)
目录
BERT - 论文精读学习笔记预备知识梗概简介摘要预训练模型(Pre-trained Model)无监督基于特征的方法(Unsupervised Feature-based Approaches)无监督微调方法(Unsupervised Fine-tuning Approaches)从监督数据迁移学习(Transfer Learning From Supervised Data)BERT预训练BERT预训练和微调深入BERT模型BERT模型可学习参数计算BERT 输入
& 输出
切词方法:WordPiece合并句子的方法:MLM预训练的细节任务1:完形填空(Masked LM, MLM)任务2:句子匹配(Next Sentence Prediction, NSP)再看微调实验Ablation Studies结论和尾声参考博文博文目录原文目录
提前说明:本系列博文主要是对参考博文的解读与重述(对重点信息进行标记、或者整段摘录加深自己的记忆和理解、融合多个博文的精髓、统合不同的代表性的案例),仅做学习记录笔记使用。与君共享,希望一同进步。
Bert开源仓库:https://github.com/google-research/bert
浅显的语言模型:Word2Vec 与 GloVe
通过对大量无标号文本数据的预训练模型来探究学习语言表征始于Word2Vec与GloVe中词的嵌入。词嵌入的由来吗?这些嵌入改变了自然语言处理任务的执行方式。现在的嵌入可以捕捉词之间的上下文关系。
这些嵌入用于训练自然语言处理下游任务的模型,做出更好的预测。即使使用较少的任务专用的数据,也可以通过利用嵌入本身的附加信息来实现这一点。
更深入、复杂的语言模型:LSTM和GRU层
这些嵌入的局限性在于他们使用了非常浅显的语言模型。这意味着他们能够捕获的信息量有限,这促使人们使用更深入、更复杂的语言模型(LSTM和GRU层)。
另一个关键的制约因素是:这些模式没有考虑到该词的上下文。以上面的“bank”为例,同一个词在不同的语境中有不同的含义。然而,像Word2Vec这样的嵌入将在上下文中为“bank”提供相同的向量。
这一宝贵信息不应被忽视
输入ELMo与ULMFiT:
自然语言处理社区用ELMo处理多义词,多义词指一个词由于上下文不同,含义也不同。从训练浅层前馈网络(Word2Vec),到逐步使用复杂的双向LSTM体系结构层来训练词嵌入。这意味着同一个单词可以基于其上下文具有多个ELMo嵌入。
从那时起,预训练就成为了自然语言处理的一种培训机制。
ULMFiT在这一点做得更深入。该框架可以训练可调的语言模型,即使在各种文档分类任务上的数据较少(少于100个示例)的情况下,也可以提供出色的结果。可以肯定地说,ULMFiT破解了自然语言处理中迁移学习的秘密。
这就是在自然语言处理中的迁移学习的黄金公式:
ULMFiT之后,大多数自然语言处理突破上述公式的要素,并取得了最新的基准。
OpenAI的GPT
OpenAI的GPT扩展了ULMFiT和ELMo带来的预训练和微调法。GPT本质上是用基于Transformer的体系结构代替了基于LSTM的语言建模体系结构。
GPT模型可以微调到超出文档分类的多个自然语言处理任务,例如常识推理、语义相似度和阅读理解。
GPT还强调了Transformer框架的重要性,该框架具有更简单的体系结构,其训练速度比基于LSTM的模型更快,还能够通过使用注意力机制来学习数据中复杂模式。
OpenAI的GPT通过实现多种先进技术证实了Transformer框架的强大和实用性。
这就是Transformer如何促成了BERT的开发,以及自然语言处理中的后续所有突破。
因此,解决自然语言处理任务的新方法可以简化为两步
1 在大型无标号文本语料库(可以是无监督或半监督)中训练语言模型;
2 根据具体的自然语言处理任务对此大型模型进行微调,以利用此模型获得的大型知识库(有监督)。
1 预训练
预训练就是,事先在一个较大的数据集上面训练好一个模型的这次训练过程(在这之后,再把这个模型拿到别的任务上面继续训练)。
BERT是一种预训练模型,通过对大量语料库进行训练,学习了语言特征和语法规则,从而具备了理解自然语言的能力。
通过预训练的语言模型可有效地提升多数下游任务,处理下游任务(迁移学习)的方法大致分为2种:
feature-based(feature-extraction)
例如,ELMo,使用task-specific architectures,包括预训练的表征作为额外的特征;
fine-tuning
例如,the Generative Pre-trained Transformer(OpenAI GPT),是训练在下游任务上的,通过简单的微调所有预训练的参数。
2 BERT的特色功能——论文解读
※ 论文解读:通过分析论文的内容和结构,理解其主旨、观点、论证方法等,从而为后续研究或应用提供参考。
※ 主题分类:利用BERT对论文主题进行分类,可以有效地将论文归类到相应的领域或研究方向。
※ 情感分析:通过BERT可以分析论文中的情感倾向,有助于研究人员了解论文作者的态度和观点。
※ 摘要生成:BERT可以用于自动生成论文的摘要,从而帮助读者快速了解论文的核心内容。
※ 实体识别:BERT可以识别论文中的实体名词,如人名、地名、机构名等,有助于进一步的信息提取和知识图谱构建。
※ 指代消解:BERT可以帮助确定论文中的代词指代对象,提高文本的可读性和理解性。
3 BERT技术原理
基于Transformer架构,通过预训练语言模型来学习语言的特征表示。
具体来说,BERT首先对大量语料库进行预训练,在这个过程中,一些单词会被随机遮盖住,然后模型需要填充这些被遮盖的单词,这个过程有助于模型更好地关注上下文信息。
此外,BERT还采用了双向编码结构,同时考虑了文本的顺序和逆序,以便更全面地捕捉上下文信息。在训练完成后,BERT可以应用于各种NLP任务,如文本分类、情感分析、摘要生成等。
实验结果:
什么是Bert?
是一个预训练的语言表征模型,是一个深度的、双向的Transformer,用来做预训练,针对一般的语言理解任务。
是一个自然语言处理框架博文1。可以毫不夸张地说,BERT已经对自然语言处理进行了显著的变革。比如使用一个在大型无标号数据集上训练的模型,在11个独立的自然语言处理任务中取得佳绩。只需稍加微调就能实现。
BERT是一个“深度双向”的模型。双向意味着BERT在训练阶段从所选文本的左右上下文中汲取信息。
实例 有两句话,都涉及“bank”一词。
BERT同时捕获左右上下文。
如果仅取左上下文或右上下文来预测单词“bank”的性质,那么在两个给定示例中,至少有一个会出错。
解决这个问题的一个方法是,在做出预测之前同时考虑左上下文和右上下文。
Bert名称由来
B=Bidirectional, E=Encoder, R=Representations, T=Transformers
Bert的目的
通过在所有层中对左右上下文进行联合条件反射,从未标记的文本中预训练深度双向表示。
优势 —— 普适性
预训练的BERT模型可以通过一个额外的输出层进行微调,从而应用于更多样的任务,如问答和语言推理,并且无需对特定的任务架构进行大量的修改。
BERT的意义
让我们能够从一个大数据集上训练好一个比较深的神经网络,用于很多不同的NLP任务上面,既简化了训练,又提升了性能。
与其他工作的关系
ELMo试图在从左到右和从右到左的上下文中训练两个LSTM语言模型,并将它们简单连接起来,解决这个问题。尽管它大大改进了现有技术,但还不够。
Bert工作是基于GPT和EMLo这两个工作的。
箭头表示从一层到下一层的信息流。
顶部的绿色框表示每个输入词的最终上下文化表示。
从上面的图像可以看出:BERT是双向的,GPT是单向的(信息只从左到右流动),ELMo是浅双向的。
这就是Masked Language Model在图像中的表示。
单向的标准语言模型,很大程度限制了预训练模型表示能力的学习。
OpenAI GPT使用从左到右的架构,Transformer的self-Attenton层的每一个token仅依赖于之前的tokens(训练任务结束),这种架构预训练的语言模型很难处理句子层级的下游任务,如Question-Answer(QA),因为Answer往往和Question的上下文有关。
问题 为什么语言生成模型是单向的?
答案 语言生成模型能够基于部分单词序列,生成下一个单词的概率分布,这种性质决定语言生成模型是单向模型。语言模型适合做生成任务,如单向语言模型GPT(生成模型)的文本生成能力很强。
BERT使用双向编码器中,单词可以看到其自身,通过上下文单词信息“填空”,BERT不是语言生成模型,可看作为语言理解模型,但这种模型不适合做生成任务,适合做利用上下文信息的标注和分类任务!
BERT预训练语言模型的特点:
基于掩盖的方式预训练双向语言模型,可以使用更深的网络架构;
基于fine-tuning处理下游任务,同时在sentence-level和token-level的多数任务中均达到出色的表现。
BERT (Bidirectional Encoder Representations from Transformers) 在未标记的文本上进行预训练,调节各个层的参数,学习上下文表示。因此只需要增加一个输出层进行微调,就能在多个任务上达到 SOTA 水平。
BERT贡献:
证明了双向预训练对于语言表示模型的重要性
减少了为特定任务精心设计网络架构的必要性
❗️ 这个是挺秀的,不用为了特定任务专门精心设计网络架构。
BERT在11个NLP任务上达到了SOTA水平
嵌入表达是NLP领域的重要组成部分,如词嵌入、句嵌入、篇章嵌入等。对于句嵌入,常用的训练方法包括:
给定前一句表示,从左到右依次生成下一句;
auto-encoder方法。
BERT与ELMo的区别:
ELMo用的是基于RNN的架构,在用于一些特定的下游任务时,需要对架构做一定的调整;
ELMo通过双向网络提取具有上下文信息的词嵌入(拼接前后向词嵌入),在多数NLP任务取得非常好的表现,如QA、情感分析、NER等。
BERT用的是Transformer,只需要改最上层的就行了,这里指的是BERT的那个额外的输出层。
最近利用无标签数据预训练的句子和篇章编码器,可生成具有上下文信息的词嵌入用于下游监督任务,这种方法的好处是下游任务从头开始学的参数较少。
OpenAI GPT在句子级别的任务中达到很好的效果,这种模型一般利用单向RNN网络或auto-encoder预训练。
BERT与GPT的区别:
在2018年,GPT是单向的,基于左边的上下文信息,来生成新的文段;
而Bert不仅用了左侧的信息,还用了右侧的信息,所以说是一个双向的操作,即Bidirectional。
BERT采用双向编码器结构,这意味着它同时考虑了文本的顺序和逆序,能够更全面地捕捉上下文信息。
bidirectional
美/ ˌbaɪdəˈrekʃənl; ˌbaɪdaɪˈrekʃənl /
adj.双向的;双向作用的
The mapping can be unidirectional or bidirectional.
映射可以是单向的或者双向的。
大规模标注数据(预训练) → 小规模标注集的类似任务(微调)
利用大规模标注数据预训练,在小规模标注集的类似任务微调,也能得到较好的效果,比如自然语言推理、机器翻译等。翻译模型可在不同语言间迁移,模型能够学习到语言的羽凡等特征表示。
CV领域也有类似处理,如在ImageNet数据集预训练,具体下游任务fine-tuning。
预训练在NLP的应用
句子层面的任务:通过整体分析来预测句子之间的关系,如,对句子情绪的识别,或者两个句子之间的关系;
词语层面的任务:标记级任务,如命名实体识别和问答(比如“张三”这个词是不是人名?还是一种食物?)
事实上,预训练在计算机视觉领域已经用了很多年了,BERT也不是自然语言处理领域第一个用预训练的,只是说,因为BERT效果太好了,以至于抢了风头。
预训练的表示,减少了对许多高度工程化的任务的特定架构的需求。
BERT是第一个基于调优的表示模型,在大量句子级和记号级的任务上实现了最先进的性能,甚至优于很多特定于某种任务的架构。
NLP中2种
预训练的策略
将语言模型预训练应用于下游任务中,或者说特征表示,有两种现成的策略:基于特征、基于微调。
基于特征(feature-based):如ELMo —— 使用特定于任务的RNN架构,把学到的特征和输入一起作为特征的表达。
基于微调(fine-tuning):如GPT —— 引入了最小的任务特定参数,并通过简单的一点点微调所有预训练参数,来对下游任务进行训练。
(GPT选择从左到右的架构,这使得每个token只能注意到它前面的token,这对sentence级的任务影响还是次要的,但对于token级的任务来说影响就很巨大。)
在当时,这些的技术限制了预训练表征的力量,主要是因为标准语言模型是单向的。
传统的单向语言模型,或者是浅层拼接两个单向语言模型,只能获取单方向的上下文信息。
标准的语言模型只能实现从左到右或从右到左的训练,不能实现真正的双向训练,这是因为双向的条件是每个单词能直接“看到自己”,并且模型可以在多层上下文中轻松的预测出目标词。
如果要获取句子层面,或者说句子之间的信息的话,就显得有些吃力了。
MLM —— 带掩码的语言模型(Masked Language Model)
BERT使用Transformer的双向编码器表示来改进基于微调的方法;
Transformer架构通过自注意力机制和学习文本中的长距离依赖关系,使得模型具有出色的全局视野。
使用带掩码的语言模型(Masked Language Model, MLM)对双向的Transformer进行预训练,缓解了单向性约束,生成深度的双向语言表征。
在BERT的训练过程中,一些单词会被有目的地遮盖住,然后模型需要尝试填充这些被遮盖的单词,从而使模型能够更好地关注上下文信息。
MLM使得能融合左右上下文,所以才能预训练深度双向Transformer,受到了Cloze的启发(1953年的论文,确实让人震惊)
※ MLM的具体工作
其实就是每一次随机选择一些字,然后“盖住”(mask),目标函数显而易见了,→(根据上下文) 预测那些被盖住的字。
※ 有点像完形填空的感觉。对,就是这样!
有了这个概念,我们就方便理解了,做完形填空的时候,就是不仅要看左边的文段,还要看右边的文段才行。
※ MLM除了完形填空之外,对于句子匹配也是有帮助的。
句子匹配:随机的选择两个句子,目标函数是要判断这两个句子在原文中是不是相邻的。
有标注的数据集一定好吗?
事实上,BERT和它之后的一些工作证明了,有些时候,在NLP任务上,通过没有标号的、大量的数据集训练的模型,效果比有标注的、规模小一些的数据集上,效果更好。
BERT架构两部曲:pre-training & fine-tuning
pre-training:在不同的任务中,基于无标签数据集进行训练;
fine-tuning:先用预训练得到的参数初始化BERT模型,再在特定的不同的下游任务上对所有参数微调。
BERT使用统一的预训练模型架构,能够处理不同的下游任务,不同下游任务的差异较小。
预训练(Pre-Training)
预训练主要的工作是:在一个没有标注的数据集上训练BERT模型。
关键点1:目标函数;
关键点2:预训练数据。
微调(Fine-Tuning)
同样是用的BERT模型,但是初始化权重为预训练过程中得到的权重。
所有的权重,在微调的过程中都会参与训练,并且用的是有标号的数据。
基于预训练得到的模型,在每个后续的下游任务中都会训练出适用于当前任务的模型。
预训练和微调的图示(以问答为例)
简而言之,就是一个多层的、双向的Transformer编码器(multi-layer bidirectional Transformer encoder)。
BERT在实现上几乎与Transformer encoder完全相同。
BERT调整了Transformer的三个参数:
(the same model size as OpenAI GPT)
表格 BERT是以Transformer为基础的,目前有两种变体。
Model | 参数个数 | |||
---|---|---|---|---|
12层(Transformer blocks) | 768 | 12个(Attention head) | 1.1亿 | |
24层(Transformer blocks) | 1024 | 16个(Attention head) | 3.4亿 |
图示 图片来源:http://jalammar.github.io/illustrated-bert/(值得好好再看看)
问题 如何把超参数换算成可学习参数的大小呢?
可学习参数主要分为两块:嵌入层、Transformer块。过程图如下。
自注意力机制本身并没有可学习参数,但是对于多头注意力,会把进入的所有K(key)、V(value)、Q(Query)都做一次投影,每次投影的维度为64,而且有
如上,前面的自注意力块有
最后再乘
输入
& 输出
目标 为了使BERT能处理大量不同的下游任务,作者将模型的输入设计成可以输入单个句子或句子对,这两种输入被建模成同一个token序列。作者使用了有30000个 token 的vocabulary 词嵌入。
输入 既可以是“句子”,也可以是“句子对”。不过事实上,这里的句子和句子对都不是狭义的概念,事实上是一个“序列”。
输入序列 第一个token都是一个特殊标记[CLS]
,该标记的最终隐藏状态用来聚合句子的表征,从而实现分类任务。对于sentence对,作者使用特殊标记[SEP]
来区分不同的句子。
输出序列 用 [CLS]
的最终隐藏状态为
因为BERT不同于一般的Transformer,BERT只有编码器,而Transformer有编码器和解码器,所以为了能够处理两个句子的情况,需要把两个句子变成一个序列。
※ BERT模型将不同的输入统一为单一输入序列,以处理多样化输入的下游任务,如单句输入的NER任务、多句输入的QA任务等。
※ 输入序列的处理方式
使用[CLS]
作为每个输入序列的第一个token,其最终一个隐藏状态的输出可用于下游分类任务
[CLS]
是每个输入示例开头的特殊标记
使用[SEP]
连接不同句子的输入序列
[SEP]
是一个特殊的标记用于区分Question / Answer(在问答案例中)
每个token加上位置嵌入(mask),区别token属于哪个句子。
切词方法1:如果说按照空格来切词的话,也就是一个词对应一个Token,那样会导致字典大小特别大,根据上文的可学习参数计算方法,这会导致参数太多而且集中在嵌入层上面。
切词方法2:而WordPiece的想法(概率 + 词根)
如果一个词在整个文段里出现的概率不大的话,应该切开,看其子序列(有可能是一个词根)。
如果一个词根出现的概率比较大的话,就只保留词根就好了,这样的话会让字典大小缩小不少。
每一个序列的第一个词都是[cls]
,代表classification,因为最后的输出要代表整个序列的一个信息,这是因为BERT使用了Transformer的编码器,所以自注意力层里的每一个词都会看输入的所有词的关系,所以可以放在第一个位置。
需要对句子进行一定的区分,以从句子层面进行分类,这里有两个办法:
为每个句子的末尾添加一个[SEP]
表示separate;
学习一个嵌入层,来知道某个句子是第一个还是第二个。
这个时候我们再回去看一下上面给出过的图,就很好理解了:
如上图,每一个Token进入BERT,得到这个Token的Embedding表示。
如上图(左),输入序列是一对句子A和B,图中各符号的意义:
句子A和B添加位置嵌入,使用[SEP]
连接为输入嵌入序列( E )
[CLS]
的最后一个隐状态
整体上的效果就是:输入一个序列,得到一个序列,最后再添加额外的输出层来得到想要的结果。
※ BERT考虑不同嵌入信息,并对不同嵌入求和得到输入序列嵌入。
对于每一个词元,进入BERT时的向量表示的是:
❶这个词元本身的Embedding + ❷它在哪个位置的Embedding + ❸位置的Embedding,如下图所示:
Token Embedding ❶ : 词元的Embedding层,对于每一个词元,输出一个对应的向量;
标记嵌入:从WordPiece标记词汇表中学习特定标记的嵌入。
Segment Embedding ❷ :A表示第一句话,B表示第二句话;
片段嵌入:BERT还可以将句子对作为任务(问答)的输入。这就是为什么它学习了第一个和第二个句子的嵌入,以帮助模型区分二者。在上面的例子中,所有标记为
Position Embedding ❸ :位置的嵌入层。输入的大小是序列最长有多长,输入的是每一个词元的位置信息(0base)
位置嵌入:BERT学习并使用位置嵌入来表达词在句子中的位置,这些为了克服Transformer的限制而添加的。与RNN不同,Transformer不能捕捉“序列”或“顺序”信息。
对于特定的标记,其输入的表示是对应的标记、片段和位置嵌入之和。这样一个综合的嵌入方案包含了很多对模型有用的信息。
由上图所示,输入序列嵌入是对不同嵌入方式的求和。
这些都是通过学习的来的,而不同于Transformer的手动构造。
※ 这些预处理步骤综合起来,使BERT具有很强的通用性。这意味着,如果不对模型的结构进行任何重大更改,就可以轻松地将其训练到多种自然语言处理任务上。
前文:使用带掩码的语言模型(Masked Language Model, MLM)对双向的Transformer进行预训练,缓解了单向性约束,生成深度的双向语言表征。
知道了切词的方法,我们再来看看所谓的“英语题”。
预训练BERT模型(Pre-training BERT)模型使用两种无监督任务:Masked LM 和 Next Sentence Prediction(NSP)。
标准条件语言模型只能按照left-to-right或者right-to-left的方式预训练模型,而Bidirectional RNN网络能够捕获上下文信息,每个单词能够间接的“see itself”,使得模型可在多层上下文中预测目标词。
为训练深度表征语言模型,BERT随机mask一定百分比的tokens,然后基于上下文预测这些被mask的tokens,这种过程称为“masked LM”(MLM),类似于完形填空。
训练过程中,将mask tokens在最后一层的隐状态接入softmax层,与标准LM处理方式一样,通过最小化mask tokens的预测分布与实际分布的交叉熵,优化语言模型。BERT的所有试验中,随机mask 15%的tokens。
在这种设置下,被masked的token的隐藏向量表示被输出到词汇表的softmax上,这就与标准语言模型设置相同。
案例 假设有这样一个句子:“我喜欢阅读Analytics Vidhya上的数据科学博客”。想要训练一个双向的语言模型,可以建立一个模型来预测序列中的遗漏单词,而不是试图预测序列中的下一个单词。
做法 将“Analytics”替换为“[MASK]”,表示丢失的标记。然后,以这样的方式训练模型,使其能够预测“Analytics”是本句中遗漏的部分:“我喜欢阅读[MASK] Vidhya上的数据科学博客。”
※ 这是Masked Language Model的关键。BERT的开发者还提出了一些进一步改进该技术的注意事项:
为了防止模型过于关注特定的位置或掩盖的标记,研究人员随机掩盖了15%的词。
掩盖的词并不总是被[MASK]替换,因为在微调时不会出现[MASK]。
因此,研究人员使用了以下方法:
[MASK]替换的概率为80%
随机词替换的概率为10%
不进行替换的概率为10%
问题 Masked LM如何用于下游任务的Fine-tuning?
Mask tokens方法可有效预训练双向深层语言模型,然而实际fine-tuning过程中不存在[MASK] token,造成预训练模型和fine-tuning不匹配。
Masked LM预训练任务的缺点在于由于[MASK]
标记不会出现在微调阶段,这就造成了预训练和微调阶段的不一致。
为了解决这个问题,作者提出了一种折中的解决方案:
随机选择15%的token,这些要被masked的token并不会真的全替换成[MASK],而是从这些token中:
随机选择80%替换成[MASK]
;
随机选择10%替换成随机token;
随机选择10%不改变原token。
然后,
BERT为匹配pre-trained model和fine-tuning,对于已经确定需要mask的tokens,BERT不总将这些“被选中”的tokens替换为[MASK],而是将其中80%会被替换为[MASK]、10%随机替换为其他token(1.5%)、10%不做改变,使得预训练阶段中也具有没有mask的输入,匹配预训练和微调。
对一个输入的词元序列,如果一个词元是由WordPiece生成的话(也就是切开来的),那就会有15%的概率随机替换成一个掩码[MASK]
。
ps:(当然,对于[CLS]
和[SEP]
就不做替换了,这属于功能性的)
整体来看,如果输入序列是1000的话,那就要预测大约150个词。
当然,这一过程是MLM预训练独有的,在微调的过程中是看不到这一个过程的,更看不到[MASK]
。
但是,这个替换的过程,也不是100%替换成[MASK]
的,具体来说是这样的方案:
80%:替换为[MASK]
10%:替换为一个随机的词元
10%:什么都不做,但是用来做预测
附录的一个例子:
Masked LM and the Masking Procedure
Assuming the unlabeled sentence is my dog is hairy, and during the random masking procedure we chose the 4-th token (which corresponding to hairy), our masking procedure can be further illustrated by
80% of the time: Replace the word with the
[MASK]
token, e.g., my dog is hairymy dog is [MASK]
10% of the time: Replace the word with a random word, e.g., my dog is hairy
my dog is apple
10% of the time: Keep the word un-changed, e.g., my dog is hairy
my dog is hairy. The purpose of this is to bias the representation towards the actual observed word.
[原因]
很多下游任务都是基于对两句话之间的关系的理解,语言模型不能直接捕获这种信息。为了训练模型理解这种句间关系,作者设计了next sentence prediction的二分类任务。
[原因]
为处理依赖不同句子关联关系的下游任务,如Question Answering(QA)和Natural Language Inference(NLI),BERT预训练sentence A是否是sentence B的下一句这种简单的二分类任务(是/否:二分类)。
具体来说:选择两个句子(sentence A 和 sentence B)作为训练数据,有50%的概率:B是A的下一句(isNEXT),有50%的概率:A和B是从语料库中随机选择的句子对(NotNext),图1中 [CLS]
的最终隐状态
实例理解 假设有一个包含100,000个句子的文本数据集。因此,将有5万个训练样本或句子对作为训练数据。
其中50%的句子对的第二句就是第一句的下一句。
剩余50%的句子对,第二句从语料库中随机抽取。
第一种情况的标签为‘IsNext’ ;第二种情况的标签为‘NotNext’。
Pre-training data(预训练数据)
作者选用了BooksCorpus(800M words)和English Wikipedia(2,500M words)作为预训练的语料库,作者只选取了Wikipedia中的文本段落,忽略了表格、标题等。为了获取长的连续文本序列,作者选用了Billion Word Benchmark这样的文档级语料库,而非打乱的句子级语料库。
BERT的预训练是在包含整个维基百科的无标签号文本的大语料库中(足足有25亿字!) 和图书语料库(有8亿字)中进行的。
NSP任务与一些研究人员提出的表征学习(Representation Learning)很相似,一些表征学习模型(feature-based)仅将句嵌入用于下游任务,BERT是将所有预训练的参数用于下游任务(fine-tuning)。
理解特殊Token的意义(BERT的两个任务)
※ BERT在输入序列头部添加
[CLS]
token,不同句子间添加[SEP]
token,掩盖词替换为[MASK]
token。
在预训练“下句预测”任务时,使用
[CLS]
token在最后一层的隐状态用于预测类别,通过训练使得从上(输出侧)至下(输入侧)的网络结构可用于分类任务,分类任务中输出侧仅使用[CLS]
token对应的隐状态。对应的[SEP]
token,BERT也能学习到其他代表连接不同句子。
在预训练“完形填空”任务时,使用
[MASK]
token在最后一层的隐状态用于预测真实词,通过训练使得不同输出位置具有语义表征能力。❗️ 看到没有,这两个任务好像可以同时训练,即在NSP任务中随机mask一些词,牛轰轰!!!
这就是BERT为什么能够成为一个真正的任务无关模型。因为它结合了Masked Language Model (MLM)和Next Sentence Prediction (NSP)的预训练任务。
无论是在QA还是语言推理层面,都是一个句子对,所以最好让其学习一些句子层面的信息。
对于句子A和B,有可能是相邻,也有可能不是:
那么相邻的就是正例;
不相邻的就是负例。
各占50%。
附录的一个例子:
Next Sentence Prediction
The next sentence prediction task can be illustrate in the following examples.
Input = [CLS] the man went to [MASK] store [SEP] he bought a gallon [MASK] milk [SEP]
Label = IsNext
Input = [CLS] the man [MASK] to the store [SEP] penguin [MASK] are flight ##less birds [SEP]
Label = NotNext
值得一提的是,可以看到有一个##
,这个意思是说:flightless
这个词在原文中不常见,所以砍成了两个词,##
的作用是表明这原本是一个词。
※ 两种不同策略的预训练精度结果(MLM & LR):
BERT基于Transformer的self-attention机制(不同位置词的距离都是1,语意表征能力强)预训练模型,可基于fine-tuning所有参数处理多数下游任务。
因为Transformer中的self-attention机制适用于很多下游任务,所以可以直接对模型进行微调。对于涉及文本对的任务,一般的做法是1 独立 encode 文本对,2 然后再应用双向的cross attention进行交互。BERT使用self-Attenton机制统一了这两个阶段,该机制直接能够实现两个串联句子的交叉编码。😧 不明白2024年8月14日 19:36:37
对于不同的任务,只需要简单地将特定于该任务的输入输出插入到BERT中,然后进行端到端的微调(end2end fine-tuning)。
对于输入,预训练中的sentence A 和sentence B能够替换成:
同义关系中的句子对;
蕴含关系中的“假设-前提”对;
问答中的“段落-问题”对;
文本分类或序列标注中的“文本-null”。
对于输出:
对于token-level的任务,如序列标注、问答,将BERT输出的token编码输入到输出层;
对于sentence-level的任务,如句子的蕴含关系、情感分析等,将[CLS]
作为输入序列的聚合编码,输入到输出层。
😧 不明白2024年8月14日 19:36:37
[CLS]输入对应输出层的隐状态用于分类任务;
其他输入对应输出层的隐状态用于序列标注或问答等任务。
由于选择了单一个编码器的架构,而不是像传统的Transformer一样有编码器和解码器,所以会有一些缺点:
与GPT比,BERT用的是编码器,GPT用的是解码器。
BERT做机器翻译、文本的摘要,也就是生成类的任务并不好做。
不过事实上,分类问题在NLP中更常见。
如下图是BERT在分类任务上的表现情况:
BERT在11项NLP任务的微调结果。
GLUE
General Language Undestanding Evaluation(GLUE) benchmark is collection of diverse natural language understanding tasks.
通用语言理解评价(GLUE)基准是多种自然语言理解任务的集合。
GLUE是多个 NLP 任务的集合。
Fine-tuning(微调):
作者设置 batch size 为 32;训练 3 个 epochs;在验证集上从(5e-5, 4e-5, 3e-5, 2e-5)中选择最优的学习率。
最后隐藏层向量 [CLS]
作为聚合表征;
分类层权重
损失函数(Loss function)是:
超参数(Hyper parameters):batch_size=32, epochs=2, learning rate among 5e-5~2e-5
对于
结果如下:
SQuAD v1.1
Stanford Question Answering Dataset. Given a question and a passage from Wikipedia containing the answer, the task is to predict the answer text span in the passage.
斯坦福问答数据集。给定一个问题和一个从维基百科摘录的包含该问题答案的文章。任务就是来预测文章中答案文本的范围。
Fine-tuning(微调):
表示输入句子(嵌入A)和文章(嵌入B)作为一个单个打包的句子;
引入一个开始向量
第 i 个答案区间的开始单词(结束单词类似)的概率是:
候选区域从位置 i 到位置 j 是:
训练目标是正确开始和结束位置的对数似然的和(sum of log-likehood)。
微调思想:真实范围值尽可能大,非真实范围值尽可能小。
SQuAD v2.0
SQuAD v2.0 extends the SQuAD v1.1 problem definition by allowing for the possibility that no short answer exists in the provided paragraph, making the problem more realistic.
SQuAD v2.0扩展了SQuAD v1.1问题定义,通过允许没有短答案存在于提供的段落中的可能性,使得问题更加现实。
Fine-tuning(微调):
基于SQuAD v1.1 BERT模型;
对待问题(没有在[CLS] token具有开始or结束的答案区间),对比没有答案区间的分数和最佳没有答案区间(不知所云😱):
预测一个非空答案,
博主:不理解怎么训练的!!!我也不知道!!!2024年8月14日 12:13:45
SWAG
Situations With Adversarial Generations. Given a sentence, the task is to choose the most plausible continuation among four choices.
具有对抗生成的场景。给定一个句子,任务是选择最可靠的连续对象(在4个选项中选1个)
Fine-tuning(微调):
构建4个输入序列,每个包括给定句子A和一个可能的连续的句子B的连结;
仅仅引入的对于特定任务的参数是一个向量,它与[CLS] token的点积表示
超参数:batch_size = 16, learning_rate = 2e-5。
大佬关于BERT SWAG实操解释
Let's assume your batch size is
8
and your sequence length is128
. Each SWAG example has4
entries, the correct one and 3 incorrect ones.
Instead of your
input_fn
returning aninput_ids
of size[128]
, it should return one of size[4, 128]
. Same for mask and sequence ids. So for each example, you will generate the sequencespredicate ending0
,predicate ending1
,predicate ending2
,predicate ending3
. Also return a label scalar which is in an integer in the range[0, 3]
to indicate what the gold ending is.After batching, your
model_fn
will get an input of shape[8, 4, 128]
. Reshape these to[32, 128]
before passing them intoBertModel
. i.e., BERT will consider all of these independently.Compute the logits as in
run_classifier.py
, but your "classifier layer" will just be a vector of size[768]
(or whatever your hidden size is).Now you have a set of logits of size
[32]
. Re-shape these back into[8, 4]
and then computetf.nn.log_softmax()
over the 4 ending for each example. Now you have log probabilities of shape[8, 4]
over the 4 endings and a label tensor of shape[8]
, so compute the loss exactly as you would for a classification problem.若不考虑原句选择4个选项的概率分布,即认为每句各自的4个选项间相互独立,则可以把SWAG任务看成是4N个独立的二分类任务,N为训练集大小。
若考虑原句选择4个选项的概率分布,则可将原句和4个选项生成的4个输入序列在一个batch里面作为BERT的输入(BERT认为每个batch的样本无关),在输出层可同时获得这4个输入序列对应的[CLS]的隐状态,选择4个选项的概率分布表示为:
Fine-tuning模型仅包含一个与输出层隐状态同维的向量
。
问题 为什么输出层不用4*hidden_size维矩阵,而仅使用hidden_size维向量?
个人理解:K分类任务输出层参数为K * hidden_size的矩阵,即输出层含K个神经元(参数维度hidden_size * K,其实只有K-1个自由神经元),而SWAG本质是二分类任务,从任务输出(是
否
是正确选项)也能看出,因此输出层用一个神经元即可。
消融实验,理解模型参数。
![]() | ![]() | ![]() |
---|---|---|
图5 | 图6 | 图7 |
Effect of Pre-training Tasks
使用相同的预训练数据、模型参数、微调参数等,评估深层双向网络的重要性。
Standard Left-to-Right LM(LTR). The addition of NSP task significantly improved the LTR model.
“No NSP”:不进行NSP任务,只进行Masked LM task;
“LTR & No NSP”:不进行NSP任务,且使用标准语言模型采用的Left-to-Right训练方法。
各模型区别如图5所示。
如果采用像ELMo那样训练LTR和RTL模型,再对结果进行拼接,有以下缺点:
相对于单个双向模型来说,表征长度翻倍,代价相对提高。
这种拼接不直观,因为对于QA任务来说,RTL任务做的事实际上是“根据答案推导问题”,这是不靠谱的。
与深度双向模型相比,这种在上下文上的双向交互的能力较弱,因为双向模型在每层都能进行双向的上下文交互。
Effect of Model Size
有关模型大小的影响的实验;
我们用一个不同的层数、隐藏单元、以及注意力头数训练了许多BERT模型,而有时使用与前文描述相同的超参数和训练过程。
作者证明了:如果模型经过充分的预训练,即使模型尺寸扩展到很大,也能极大改进训练数据规模较小的下游任务。
各模型区别如图6所示。
Feature-based Approach with BERT
将BERT应用于Feature-based的方法
feature-based的方法是从预训练模型中提取固定的特征,不对具体任务进行微调。这样的方法也有一定的优点:
1 并非所有任务都能用Transformer架构简单表示,因此这些任务都需要添加特定的架构;
2 feature-based的方法还有一定的计算成本优势。
作者进行了如下实验:在CoNLL-2003数据集上完成NER任务,不适用CRF输出,而是从一到多个层中提取出激活值,输入到2层768维的BiLSTM中,再直接分类。
某些下游任务可能无法表示成Transformer encoder架构,所以有必要考虑能够处理特定任务的预训练模型架构。此外,预先训练模型学习特征表示,之后直接用这些特征表示处理下游任务,计算代价更小。如拼接BERT的后四层作为token特征表示,NER任务的F1值仅比使用BERT fine-tuning低0.3。
各模型区别如图7所示。
结论说明:无论是否进行微调,BERT模型都是有效的。
博文2的作者
在本文发布的当时,语言模型迁移学习的经验改进表明,丰富的无监督预训练是许多语言理解系统的组成部分,这个效果是非常好的。
使得训练集比较少的任务也能够使用深度神经网络,获得比较好的效果。
特别是,这些结果使低资源任务也能从深度单向架构中受益。BERT的主要贡献是进一步将这些发现推广到深度双向架构,允许相同的预训练模型成功地处理广泛的NLP任务。
博文4的作者
个人认为BERT的意义在于:
成功实践了pre-training + fine-tuning的深度学习范式;
发掘了在NLP中“深度双向架构”在预训练任务中的重要意义。
【论文解读】BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
BERT:论文解读的利器与展望 - 短文
BERT - 论文精读学习笔记预备知识梗概简介摘要预训练模型(Pre-trained Model)无监督基于特征的方法(Unsupervised Feature-based Approaches)无监督微调方法(Unsupervised Fine-tuning Approaches)从监督数据迁移学习(Transfer Learning From Supervised Data)BERT预训练BERT预训练和微调深入BERT模型BERT模型可学习参数计算BERT 输入
& 输出
切词方法:WordPiece合并句子的方法:MLM预训练的细节任务1:完形填空(Masked LM, MLM)任务2:句子匹配(Next Sentence Prediction, NSP)再看微调实验Ablation Studies结论和尾声参考博文博文目录原文目录
BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding 1 Introduction 2 Related Work 2.1 Unsupervised Feature-based Approaches 2.2 Unsupervised Fine-tuning Approaches 2.3 Transfer Learning from Supervised Data 3 BERT 3.1 Pre-training BERT 3.2 Fine-tuning BERT 4 Experiments 4.1 GLUE 4.2 SQuAD v1.1 4.3 SQuAD v2.0 4.4 SWAG 5 Ablation Studies 5.1 Effect of Pre-training Tasks 5.2 Effect of Model Size 5.3 Feature-based Approach with BERT 6 Conclusion References
博文免责声明
本条博文信息主要整合自网络,部分内容为自己的理解写出来的,如有断章截句导致不正确或因个人水平有限未能详尽正确描述的地方,敬请各位读者指正;
引用出处可能没有完全追溯到原始来源,如因此冒犯到原创作者,请联系本人更正/删除;
博文的发布主要用于自我学习,其次希望帮助到有共同疑惑的朋友。